Appendix D — Assignment 4 (Classes and Objects)

Instructions

  1. You may talk to a friend, discuss the questions and potential directions for solving them. However, you need to write your own solutions and code separately, and not as a group activity.

  2. Do not write your name on the assignment.

  3. Write your code in the Code cells and your answer in the Markdown cells of the Jupyter notebook. Ensure that the solution is written neatly enough to understand and grade.

  4. Use Quarto to print the .ipynb file as HTML. You will need to open the command prompt, navigate to the directory containing the file, and use the command: quarto render filename.ipynb --to html. Submit the HTML file.

  5. There are 6 points for clealiness and organization. The code should be commented and clearly written with intuitive variable names. For example, use variable names such as number_input, factor, hours, instead of a,b,xyz, etc.

  6. The assignment is worth 100 points, and is due on 5th November 2022 at 11:59 pm.

  7. There is a Bonus question worth 25 points. You can score 125 out of 100 in the assignment if all is correct. However, there is no partial credit for the bonus question.

D.1 Password Manager

Define a class named PasswordManagerUpdated that inherits the class PasswordManager defined in Practice exercise 1. The class PasswordManagerUpdated should have two methods, other than the constructor:

The method set_password(new_password) that sets a new password. The new password must only be accepted if it does not have any punctuations in it, and if it is not the same as one of the old passwords. If the new password is not acceptable, then one of the appropriate messages should be printed - (a) Cannot have punctuation in password, try again, or (b) Old password cannot be reused, try again. The new password is a parameter to this method.

The method suggest_password() that randomly sets and returns a password as a string comprising of 15 randomly chosen letters of the English language. Letters may be repeated as well.

Code
past_passwords = ['titanic1911','ibiza1972','montecarlo799']

Hint:

  1. For generating letters, use str.lowercase()

  2. For randomly selecting letters, use random.randint()

  3. For iterating through punctuations, use from string import punctuation.

After defining the class, instantiate an object of this class with past_passwords. Then:

D.1.1

Check the attribute old_passwords.

(2 points)

D.1.2

Check the method get_password()

(2 points)

D.1.3

Try re-setting the password to ‘ibiza1972’, and then check the current password.

(4 points)

D.1.4

Try re-setting the password to ‘oktoberfest%2022’, and then check the current password.

(6 points)

D.1.5

Try re-setting the password to ‘oktoberfest2022’, and then check the current password.

(2 points)

D.1.6

Use the method suggest_password() to set a new password.

(6 points)

D.1.7

Check the is_correct() method by entering the correct password as set in the previous question.

(2 points)

D.2 SMS store manager

Create a new class, named as SMS_store_manager. This class will be used to store and manage SMSs of a person’s cellphone. An object of this class, say my_inbox, will be initialized with a list of existing messages. The class attribute messages will store the existing messages during instantiation:

Code
my_inbox(existing_messages)

Each message in the list will be represented as a dictionary. A sample message is shown below:

Code
{'has_been_viewed':True, 'from_number':9348593356, time_arrived='19:50', 'date':'2022-10-27','text_of_SMS':'Hi, how about lunch at 11?'}

The class should provide these methods:

Code
my_inbox.add_new_arrival(from_number, time_arrived, text_of_SMS)
#Makes new SMS dictionary, inserts it after other messages
#in the store, i.e, in the list of messages. When creating this message, its
#'has_been_viewed' status is set False.

my_inbox.message_count()
#Returns the number of sms messages in my_inbox

my_inbox.get_unread_messages()
#Returns unread messages, i.e., messages with 'has_been_viewed' status as False
#Also changes the status of 'has_been_viewed' to True for all messages returned
#While returning unread messages, the 'has_been_viewed' status must not be returned

my_inbox.delete(i)     # Delete the message at index i
my_inbox.clear()       # Delete all messages from inbox

Once you define the class, instantiate an object of this class, and call it harry_messages. Initialize the object with the existing messages below.

Code
existing_messages = [{'has_been_viewed':False, 'from_number':8769038451, 'time':'09:30','date':'2022-10-27','text_of_SMS':'Hi, how about lunch at 11?'},
                        {'has_been_viewed':False, 'from_number':9579038373, 'time':'19:30','date':'2022-10-20', 'text_of_SMS':'Your order has arrived'},
                        {'has_been_viewed':True, 'from_number':8639568726, 'time':'10:30','date':'2022-09-30','text_of_SMS':'Card not present on American Express acc ending 54345 Sep 30 Amount $45.43 Merch: TOMATEFRESHKITCHEN.COM if unrecognized call # on Card'},
                        {'has_been_viewed':False, 'from_number':4567653456, 'time':'11:50','date':'2022-09-15','text_of_SMS':'Hi Brooke, we are confirming your Covid vaccine appointment on Thursday at 1900 hours'},
                        {'has_been_viewed':False, 'from_number':5646786643, 'time':'18:50','date':'2022-09-11','text_of_SMS':'Where is the party bro?'},
                        {'has_been_viewed':False, 'from_number':9845543492, 'time':'17:10','date':'2022-09-10','text_of_SMS':'Free trial of ScanApp for 7 days for clear scanned documents, cancel anytime, $10.99 per month after 7 days'},
                        {'has_been_viewed':True, 'from_number':8793450987, 'time':'13:20','date':'2022-08-31','text_of_SMS':'Hey Brooke, I have sent you my resume for feedback'},
                        {'has_been_viewed':True, 'from_number':874556445, 'time':'07:20','date':'2022-08-19','text_of_SMS':'Which route are we taking for the run today?'},
                        {'has_been_viewed':True, 'from_number':998456435, 'time':'07:20','date':'2022-07-31','text_of_SMS':'Reservation confirmed at the New York Plaza hotel for 2022-08-09 to 2022-09-14.'},
                        {'has_been_viewed':True, 'from_number':8769038451, 'time':'07:20','date':'2022-07-25','text_of_SMS':'Lets catchup sometime, it has been so long!'},
                        {'has_been_viewed':True, 'from_number':7739984533, 'time':'07:20','date':'2022-07-24','text_of_SMS':'Do you want to be rich today? Do you want to be your own boss? Check out beyourownboss.com. Register today for just $5!!!'},
                        {'has_been_viewed':True, 'from_number':3443498738, 'time':'07:20','date':'2022-07-22','text_of_SMS':'Want to lose weight? Get Dr. Oz magic pills @ozpills.com. Satisfaction guaranteed.'}]

Use the object harry_messages to:

D.2.1

Add a new message below:

Code
from_number=8749373884;
time='07:25';
date='2022-10-29'
text_of_SMS='Hey, I want my bike back.'

(4 points)

D.2.2

Count the number of messages.

(2 points)

D.2.3

Print all the unread messages.

(6 points)

D.2.4

Try printing all the unread messages again (Nothing should show up as all messages were read in in the previous question).

(4 points)

D.2.5

Clear the inbox, and then count the number of messages.

(4 points)

D.3 Personalized SMS store manager

Inherit the class developed in the previous question to create a new class SMS_personalized_store_manager. This class will inherit all the methods of the class SMS_store_manager. However, it will have the following differences as compared to the parent class:

  1. Instantiation

    1. During instantiation, it will initialize two additional attributes - spam_words, and update_words, along with the messages attribute which stores existing messages. Use the lists below to initialize the attributes of the class.

    2. Each message will be tagged as spam, update, or personal as follows. If the message contains any word / phrase in the list spam_words, then it will be tagged as spam. If the messege is not tagged as spam, and it contains any word / phrase in the list update_words, then it will be tagged as update. If the message has not been tagged as spam or update, then it will be tagged as personal. The tag will appear as an additional key-value pair in the dictionary of each message, where the key will be tag, and the value will be 'spam', 'update' or 'personal'.

A message after tagging may look like:

Code
{'has_been_viewed':True, 'from_number':9348593356, time_arrived='19:50', 'date':'2022-10-27','text_of_SMS':'Hi, how about lunch at 11?', 'tag':'personal'}
Code
#Lists for initializing the attributes of the class
existing_messages = [{'has_been_viewed':False, 'from_number':8769038451, 'time':'09:30','date':'2022-10-27','text_of_SMS':'Hi, how about lunch at 11?'},
                        {'has_been_viewed':False, 'from_number':9579038373, 'time':'19:30','date':'2022-10-20', 'text_of_SMS':'Your order has arrived'},
                        {'has_been_viewed':True, 'from_number':8639568726, 'time':'10:30','date':'2022-09-30','text_of_SMS':'Card not present on American Express acc ending 54345 Sep 30 Amount $45.43 Merch: TOMATEFRESHKITCHEN.COM if unrecognized call # on Card'},
                        {'has_been_viewed':False, 'from_number':4567653456, 'time':'11:50','date':'2022-09-15','text_of_SMS':'Hi Brooke, we are confirming your Covid vaccine appointment on Thursday at 1900 hours'},
                        {'has_been_viewed':False, 'from_number':5646786643, 'time':'18:50','date':'2022-09-11','text_of_SMS':'Where is the party bro?'},
                        {'has_been_viewed':False, 'from_number':9845543492, 'time':'17:10','date':'2022-09-10','text_of_SMS':'Free trial of ScanApp for 7 days for clear scanned documents, cancel anytime, $10.99 per month after 7 days'},
                        {'has_been_viewed':True, 'from_number':8793450987, 'time':'13:20','date':'2022-08-31','text_of_SMS':'Hey Brooke, I have sent you my resume for feedback'},
                        {'has_been_viewed':True, 'from_number':874556445, 'time':'07:20','date':'2022-08-19','text_of_SMS':'Which route are we taking for the run today?'},
                        {'has_been_viewed':True, 'from_number':998456435, 'time':'07:20','date':'2022-07-31','text_of_SMS':'Reservation confirmed at the New York Plaza hotel for 2022-08-09 to 2022-09-14.'},
                        {'has_been_viewed':True, 'from_number':8769038451, 'time':'07:20','date':'2022-07-25','text_of_SMS':'Lets catchup sometime, it has been so long!'},
                        {'has_been_viewed':True, 'from_number':7739984533, 'time':'07:20','date':'2022-07-24','text_of_SMS':'Do you want to be rich today? Do you want to be your own boss? Check out beyourownboss.com. Register today for just $5, or book an appointment at 985-998-3452!!!'},
                        {'has_been_viewed':True, 'from_number':3443498738, 'time':'07:20','date':'2022-07-22','text_of_SMS':'Want to lose weight? Get Dr. Oz magic pills @ozpills.com. Satisfaction guaranteed.'}]
spam_words=['100% more', '100% free', '100% satisfied', 'Additional income', 'Be your own boss', 'Best price', 'Big bucks', 'Billion', 'Cash bonus', 'Cents on the dollar', 'Consolidate debt', 'Double your cash', 'Double your income', 'Earn extra cash', 'Earn money', 'Eliminate bad credit', 'Extra cash', 'Extra income', 'Expect to earn', 'Fast cash', 'Financial freedom', 'Free access', 'Free consultation', 'Free gift', 'Free hosting', 'Free info', 'Free investment', 'Free membership', 'Free money', 'Free preview', 'Free quote', 'Free trial', 'Full refund', 'Get out of debt', 'Get paid', 'Giveaway', 'Guaranteed', 'Increase sales', 'Increase traffic', 'Incredible deal', 'Lower rates', 'Lowest price', 'Make money', 'Million dollars', 'Miracle', 'Money back', 'Once in a lifetime', 'One time', 'Pennies a day', 'Potential earnings', 'Prize', 'Promise', 'Pure profit', 'Risk-free', 'Satisfaction guaranteed', 'Save big money', 'Save up to', 'Special promotion']
update_words = ['Your order', 'appointment', 'Reservation confirmed', 'Card Not Present', 'Payment confirmation', 'Your payment']
  1. The class will have two additional methods:

    1. get_unread_messages_by_category(): This method will return all the unread messages of a particular category, i.e, 'spam', 'update' or 'personal'. The method will accept the category as an argument. If no argument is specified by the user for the category, then all the unread messages must be displayed. Once unread messages are returned, they will be marked as read. While returning unread messages, the has_been_viewed status must be changed to True, but the status itself must not be returned.

    2. get_messages_by_category(): This method will return all the messages (both read or unread) of a particular category, i.e, 'spam', 'update' or 'personal'. The method will accept the category as an argument. If no argument is specified by the user for the category, then all the messages must be returned.

  2. The class will modify the method add_new_arrival(self,from_number, time, date, text_of_SMS) of the parent class to tag a new message as 'spam', 'update' or 'personal'.

Once you define the class, instantiate an object of this class with the lists existing_messages, spam_words and update_words, and call it ron_messages:

D.3.1

Add a new message below:

Code
from_number=8749373884;
time='07:25';
date='2022-10-29'
text_of_SMS='Hey, I want my bike back.'

(6 points)

D.3.2

Print all the unread messages tagged as 'personal'. Use the method get_unread_messages_by_category().

(10 points)

D.3.3

Print all the unread messages tagged as 'update'. Use the method get_unread_messages_by_category().

(10 points)

D.3.4

Print all the unread messages. Use the method get_unread_messages().

(10 points)

D.3.5

Print all the messages tagged as 'spam'. Use the method get_messages_by_category().

(7 points)

D.3.6

Print all the messages tagged as 'update'. Use the method get_messages_by_category().

(7 points)

D.4 Bonus question: Creating a new datatype - list of dictionaries

Read movie_data with the code below.

Code
import json
with open("movies.json", encoding="utf8") as file:
    movie_data=json.load(file)

Inherit the in-built python class list() to create a new class list_dict(). This class will be used for objects that are a list of dictionaries, where all the dictionaries in the list have the same keys. Add a method in this class, named as sort_by_dict_value() that sorts the dictionaries of the list based on the values of the desired key in the dictionaries. Sorting can be done in ascending or descending order depending on the user. The key to be used for sorting and the order (ascending / descending) will be parameters to the method sort_by_dict_value(). If the sorting order is unspecified, use ascending as default.

Instantiate an object of the class list_dict() with movie_data.

If the name of the object is mov, then the method sort_by_dict_value() may be called as: mov.sort_by_dict_value(movie_parameter, ascending = True)

where movie_parameter can be any key of the dictionaries, using the values of which the list of dictionaries has to be sorted.

D.4.1

Use the method sort_by_dict_value() to sort the list of dictionaries in increasing order of Production Budget. What is the name of the 45th movie in the sorted list of dictionaries?

D.4.2

Use the method sort_by_dict_value() to sort the list of dictionaries in decreasing order of Worldwide Gross. What is the name of the 2nd movie in the sorted list of dictionaries?

(25 points - No partial credit)